
#include "IGUIListBox.h"
#include "irrArray.h"

#include <IGUIScrollbar.h>
#include <IrrArray.h>
#include <SColor.h>


class CListBox : public IGUIListBox
{

public:
	//! constructor
	CListBox(IGUIEnvironment* environment, IGUIElement* parent, 
		s32 id, core::rect<s32> rectangle, bool clip=true,
		bool drawBack=false, bool moveOverSelect=false);

	//! destructor
	 ~CListBox();

	//! returns amount of list items
	virtual u32 getItemCount() const;

	//! returns string of a list item. the id may be a value from 0 to itemCount-1
	virtual const wchar_t* getListItem(u32 id) const;

	//! adds an list item, returns id of item
	virtual u32 addItem(const wchar_t* text);

	//! clears the list
	virtual void clear();

	//! returns id of selected item. returns -1 if no item is selected.
	virtual s32 getSelected() const;

	//! sets the selected item. Set this to -1 if no item should be selected
	virtual void setSelected(s32 id);

	//! called if an event happened.
	virtual bool OnEvent(const SEvent& event);

	//! draws the element and its children
	void draw();

	//! adds an list item with an icon
	//! \param text Text of list entry
	//! \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon
	//! \return
	//! returns the id of the new created item
	virtual u32 addItem(const wchar_t* text, s32 icon);

	//! Returns the icon of an item
	virtual s32 getIcon(u32 id) const;

	//! removes an item from the list
	virtual void removeItem(u32 id);

	virtual s32 getItemAt(s32 xpos, s32 ypos) const;

	//! Sets the sprite bank which should be used to draw list icons. This font is set to the sprite bank of
	//! the built-in-font by default. A sprite can be displayed in front of every list item.
	//! An icon is an index within the icon sprite bank. Several default icons are available in the
	//! skin through getIcon
	virtual void setSpriteBank(IGUISpriteBank* bank);
	
	//! sets if automatic scrolling is enabled or not. Default is true.
	virtual void setAutoScrollEnabled(bool scroll);

	//! returns true if automatic scrolling is enabled, false if not.
	virtual bool isAutoScrollEnabled() const;

	//! Update the position and size of the listbox, and update the scrollbar
	virtual void updateAbsolutePosition();

	//! Writes attributes of the element.
	virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;

	//! Reads attributes of the element
	virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);

	//! set all item colors at given index to color
	virtual void setItemOverrideColor(u32 index, const video::SColor &color);

	//! set all item colors of specified type at given index to color
	virtual void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, const video::SColor &color);

	//! clear all item colors at index
	virtual void clearItemOverrideColor(u32 index);

	//! clear item color at index for given colortype 
	virtual void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType);

	//! has the item at index it's color overwritten?
	virtual bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const;

	//! return the overwrite color at given item index. 
	virtual video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const;

	//! return the default color which is used for the given colorType
	virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const;

	//! set the item at the given index 
	virtual void setItem(u32 index, const wchar_t* text, s32 icon);

	virtual void setItemHeight( s32 height );
		
	virtual void setDrawBackground(bool draw);

	//! Insert the item at the given index 
	//! Return the index on success or -1 on failure.
	s32 insertItem(u32 index, const wchar_t* text, s32 icon);

	//! Swap the items at the given indices
	virtual void swapItems(u32 index1, u32 index2);

	void SetSearchText (const core::stringw& text);
	void SetGameText (const core::stringc text);
	int getTreeNodeID (int sel);
	void Sort(bool bButton = false);
	bool inSearch(int sel);
	void setSelected(const wchar_t* textSel);
	core::stringw m_searchText;
	core::stringc m_gameText;
	bool sortAscending;
	array<s32> SelectedList;

private:

	struct ListItem
	{
		ListItem() : icon(-1) 
		{}

		core::stringw text;
		s32 icon;

		// A multicolor extension
		struct ListItemOverrideColor
		{
			ListItemOverrideColor() : Use(false) {}
			bool Use;
			video::SColor Color;
		};
		ListItemOverrideColor OverrideColors[EGUI_LBC_COUNT];
		bool operator< (ListItem ls)
		{
			core::stringw sw = text.subString(0,text.findFirst(' '));
			int id = 0;
			size_t   size;
			char  charList[10];
			wcstombs_s(&size, charList, (size_t)10, 
			sw.c_str(), (size_t)10 );	
			sscanf_s(charList,"%d",&id);

			sw = ls.text.subString(0,ls.text.findFirst(' '));
			int idls = 0;
			wcstombs_s(&size, charList, (size_t)10, 
			sw.c_str(), (size_t)10 );	
			sscanf_s(charList,"%d",&idls);

			return id<idls;
		}
	};

	void recalculateItemHeight();
	void selectNew(s32 ypos, bool onlyHover=false);
	void selectAddNew(s32 ypos, bool onlyHover=false);	
	void recalculateScrollPos();

	// extracted that function to avoid copy&paste code
	void recalculateItemWidth(s32 icon);

	// get labels used for serialization
	bool getSerializationLabels(EGUI_LISTBOX_COLOR colorType, core::stringc & useColorLabel, core::stringc & colorLabel) const;

	core::array< ListItem > Items;
	s32 Selected;	
	s32 ItemsInSearch;
	s32 ItemHeight;
	s32 TotalItemHeight;
	s32 ItemsIconWidth;
	gui::IGUIFont* Font;
	gui::IGUISpriteBank* IconBank;
	gui::IGUIScrollBar* ScrollBar;
	bool Selecting;
	bool DrawBack;
	bool MoveOverSelect;
	u32 selectTime;
	bool AutoScroll;
	core::stringw KeyBuffer;
	u32 LastKeyTime;
	bool HighlightWhenNotFocused;
};
